require 'digest/sha1'
class User < ActiveRecord::Base

    has_many :posts
    has_many :replies
    
    has_many :topics
    has_many :topic_replies
    
    has_many :sites
    
    has_many :talks
  
    belongs_to :district
    belongs_to :community
    
    has_many :comments
    
    #has_many :created_sites, :class_name => "Site", :foreign_key => "created_user_id"
  
    #has_and_belongs_to_many :groups
    has_many :group_users, :dependent => :destroy
    has_many :groups, :through => :group_users
    
    has_many :user_messages, :dependent => :destroy
    has_many :messages, :through => :user_messages
    
    #has_and_belongs_to_many :friends, :join_table => "friends", :foreign_key => "from_id", :association_foreign_key => "to_id"
    has_many_friends
    
    #has_and_belongs_to_many :tags
    has_many :user_tags, :dependent => :destroy
    has_many :tags, :through => :user_tags
    
    # Virtual attribute for the unencrypted password
    attr_accessor :password
     
    file_column :image, :magick => { 
            #:versions => { "thumb" => "40x40>", :crop => "1:1" }
            :versions => { :square => { :crop => "1:1", :size => "40x40", :name => "thumb"}}
          }
    
    cattr_reader :per_page
    @@per_page = 15
    
    validates_presence_of     :login, :email
    validates_presence_of     :password,                   :if => :password_required?, :message => "密码不能为空"
    validates_presence_of     :password_confirmation,      :if => :password_required?, :message => "确认密码不能为空"
    
    validates_format_of		:login, :with => /^\w+$/, :message => "用户名无效"
    validates_format_of		:email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :message => "邮件地址无效"
    validates_format_of		:password, :if => :password_required?, :with => /^\w+$/, :message => "密码无效"
    validates_format_of		:password_confirmation, :if => :password_required?, :with => /^\w+$/, :message => "密码无效"
    
    validates_length_of       :login,    :within => 5..20, :too_long => "用户名在5到20位之间", :too_short => "用户名在5到20位之间"
    validates_length_of       :email,    :within => 5..50, :too_long => "邮件地址在5到50位之间", :too_short => "邮件地址在3到50位之间"
    validates_length_of       :password, :within => 6..20, :if => :password_required?, :too_long => "密码在6到20位之间", :too_short => "密码在6到20位之间"
    validates_confirmation_of :password,                   :if => :password_required?, :message => "密码不匹配"
    
    #validates_length_of       :nickname,    :maximum => 50, :message => "昵称长度不能超过50位"
  
    validates_uniqueness_of   :email, :case_sensitive => false, :message => "该邮箱已经被注册"
    validates_uniqueness_of   :login, :case_sensitive => false, :message => "该用户名已经被注册"
    before_save :encrypt_password
    
    before_create :make_activation_code
  
    analyzer = Ferret::Analysis::PerFieldAnalyzer.new(Ferret::Analysis::StandardAnalyzer.new)
    analyzer[:login] = Ferret::Analysis::RegExpAnalyzer.new(/./, false)
    analyzer[:email] = Ferret::Analysis::RegExpAnalyzer.new(/./, false)
    analyzer[:nickname] = Ferret::Analysis::RegExpAnalyzer.new(/./, false)
    analyzer[:search_location] = Ferret::Analysis::RegExpAnalyzer.new(/./, false)
    #acts_as_ferret({:fields => [ 'login', 'email', 'nickname' ]},
    #					{:analyzer=> analyzer})
    acts_as_ferret({:fields => {:login => {:store => :yes}, :email => {:store => :yes}, :nickname => {:store => :yes}, :search_location => {:store => :yes}}}, {:analyzer=> analyzer})
    # Authenticates a user by their login name and unencrypted password.  Returns the user or nil.
    
    def self.authenticate(login, password)
        #u = find_by_login(login) # need to get the salt
        #u && u.authenticated?(password) ? u : nil
            
        u = find :first, :conditions => ['login = ? and activated_at IS NOT NULL and is_banned = 0', login]
        u && u.authenticated?(password) ? u : nil
    end
    
    def self.admin_authenticate(login, password)
      u = find :first, :conditions => ["login = 'admin'"]
      u && u.authenticated?(password) ? u : nil
    end
    
    # Encrypts some data with the salt.
    def self.encrypt(password, salt)
      Digest::SHA1.hexdigest("--#{salt}--#{password}--")
    end

    # Encrypts the password with the user salt
    def encrypt(password)
      self.class.encrypt(password, salt)
    end
    
    def authenticated?(password)
      crypted_password == encrypt(password)
    end
    
    def remember_token?
      remember_token_expires_at && Time.now.utc < remember_token_expires_at 
    end
    
    # These create and unset the fields required for remembering users between browser closes
    def remember_me
      self.remember_token_expires_at = 2.weeks.from_now.utc
      self.remember_token            = encrypt("#{email}--#{remember_token_expires_at}")
      save(false)
    end
    
    def forget_me
      self.remember_token_expires_at = nil
      self.remember_token            = nil
      save(false)
    end
    
    #我管理的小组
    def groups_admin
        query = ""
        query << "select groups.*"
        query << " from groups INNER JOIN group_users"
        query << " ON groups.id = group_users.group_id"
        query << " where (group_users.is_admin = 't'"
        query << " and group_users.user_id = '"
        query << self.id.to_s
        query << "')"
        groups = Group.find_by_sql [query]
        groups
    end
  
    #是否是系统管理员
    def is_admin?
        if self.login == "admin"
	    true
	else
	    false
	end
    end
  
    def is_myfriend?(user)
        frd = self.friends.find(:first, :conditions => ["id = ?", user.id])
        !frd.nil?
    end
  
    def is_group_user(group)
        grp = self.groups.find(:first, :conditions => ["group_users.group_id = ?", group.id])
	!grp.nil?
    end
  
    def is_group_admin(group)
        users = User.find(:all, :conditions => ["users.id = ? and group_users.user_id = ? and group_users.group_id = ? and group_users.is_admin = 't'", self.id, self.id, group.id],
                                :select => ["users.*"],
        			:from => ["users, group_users"])
        !users.empty?
    end
  
    def could_quit(group)
        flag = false
        if (self.is_group_admin(group) && group.num_of_admins > 1) || (!self.is_group_admin(group) && group.num_of_admins > 0)
            flag = true
        else
            flag = false
        end
        flag
    end
  
    def is_live_in(communities)
        flag = false
        for community in communities
            if community == self.community
                flag = true
            end
        end
        flag
    end
  
    def forgot_password
        @forgotten_password = true
        self.make_password_reset_code
    end

    def reset_password
        # First update the password_reset_code before setting the 
        # reset_password flag to avoid duplicate email notifications.
        update_attributes(:password_reset_code => nil)
        @reset_password = true
    end

    def recently_reset_password?
        @reset_password
    end

    def recently_forgot_password?
        @forgotten_password
    end

    # Activates the user in the database.
    def activate
        @activated = true
        update_attributes(:activated_at => Time.now.utc, :activation_code => nil)
    end

    # Returns true if the user has just been activated.
    def recently_activated?
        @activated
    end
   
    def display_name
        if self.nickname.nil? || self.nickname.length <= 0
            self.login
        else
            self.nickname
        end
    end
    
    def current_status
        offline_status = "<img src='/images/lightbulb_off.png'/><span color='#333'>离线</span>"
        online_status = "<img src='/images/lightbulb.png'/><span color='#333'>在线</span>"
        return offline_status if self.last_action_at.nil?
        if Time.now.utc - self.last_action_at > 5*60
            offline_status
        else
            online_status
        end
    end
    
    def add_scores(score)
        self.scores = self.scores + score
        self.save!
    end
   
    def before_save
        if !self.nickname.nil?
            self.nickname = self.nickname.gsub(/^\<(script|frame)/i, '')
        end
        if !self.intro.nil? 
            self.intro = self.intro.gsub(/^\<(script|frame)/i, '')
        end
    end
   
    def setpos(community)
        self.community_id = community.id
        self.district_id = community.district_id
        self.search_location = community.district.title + community.title
        self.join_community_at = Time.now.utc
        self.save!
    end
   
    protected

    def make_password_reset_code
        self.password_reset_code = Digest::SHA1.hexdigest( Time.now.utc.to_s.split(//).sort_by {rand}.join )
    end
   
    # If you're going to use activation, uncomment this too
    def make_activation_code
        self.activation_code = Digest::SHA1.hexdigest( Time.now.utc.to_s.split(//).sort_by {rand}.join )
    end

    # before filter 
    def encrypt_password
        return if password.blank?
        self.salt = Digest::SHA1.hexdigest("--#{Time.now.utc.to_s}--#{login}--") if new_record?
        self.crypted_password = encrypt(password)
    end
    
    def password_required?
        crypted_password.blank? || !password.blank?
    end
end